/*
* Copyright 2004-2010 mb_sx@hotmail.com
* All Rights Reserved.
*/
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace DeskNotes
{
	/// <summary>
	/// Summary description for NotifyForm.
	/// </summary>
	public class NotifyForm : System.Windows.Forms.Form
	{
		public event NotifyActionHandler NotificationHandler;

		/// <summary>
		/// Actions describing how user interacted with NotifyForm
		/// </summary>
		/// <value>Closed: Close button clicked
		/// Selected: Linked text clicked
		/// Missed: User did not interact with Notification window
		/// </value>
		public enum Action : short 
		{
			Closed, 
			Selected,
			Missed
		}

		/// <summary>
		/// This enumeration keeps track of what the toast window
		/// is doing.
		/// </summary>
		private enum NotifyState : short
		{
			Nothing,
			FadeUp,
			Visible,
			FadeDown
		}
		internal System.Windows.Forms.LinkLabel lblText;
		private System.Windows.Forms.Timer timerFading;
		private System.Windows.Forms.PictureBox pictureBox1;
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.ToolTip toolTip1;
		private System.Windows.Forms.PictureBox pictureBox2;

		private NotifyState state = NotifyState.FadeUp;

		internal string NoteText
		{
			set 
			{
				lblText.Text = value;
				lblText.LinkArea = new LinkArea(0, value.Length);
			}
		}

		public NotifyForm()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
			
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			NotificationHandler = null;
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NotifyForm));
            this.lblText = new System.Windows.Forms.LinkLabel();
            this.timerFading = new System.Windows.Forms.Timer(this.components);
            this.pictureBox1 = new System.Windows.Forms.PictureBox();
            this.label1 = new System.Windows.Forms.Label();
            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
            this.pictureBox2 = new System.Windows.Forms.PictureBox();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
            this.SuspendLayout();
            // 
            // lblText
            // 
            resources.ApplyResources(this.lblText, "lblText");
            this.lblText.Cursor = System.Windows.Forms.Cursors.Hand;
            this.lblText.Name = "lblText";
            this.toolTip1.SetToolTip(this.lblText, resources.GetString("lblText.ToolTip"));
            this.lblText.MouseLeave += new System.EventHandler(this.NotifyForm_MouseLeave);
            this.lblText.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.lblText_LinkClicked);
            this.lblText.MouseEnter += new System.EventHandler(this.NotifyForm_MouseEnter);
            // 
            // timerFading
            // 
            this.timerFading.Tick += new System.EventHandler(this.FadeTick);
            // 
            // pictureBox1
            // 
            resources.ApplyResources(this.pictureBox1, "pictureBox1");
            this.pictureBox1.Name = "pictureBox1";
            this.pictureBox1.TabStop = false;
            this.pictureBox1.MouseLeave += new System.EventHandler(this.NotifyForm_MouseLeave);
            this.pictureBox1.MouseEnter += new System.EventHandler(this.NotifyForm_MouseEnter);
            // 
            // label1
            // 
            this.label1.FlatStyle = System.Windows.Forms.FlatStyle.System;
            resources.ApplyResources(this.label1, "label1");
            this.label1.Name = "label1";
            this.label1.MouseLeave += new System.EventHandler(this.NotifyForm_MouseLeave);
            this.label1.MouseEnter += new System.EventHandler(this.NotifyForm_MouseEnter);
            // 
            // pictureBox2
            // 
            resources.ApplyResources(this.pictureBox2, "pictureBox2");
            this.pictureBox2.Name = "pictureBox2";
            this.pictureBox2.TabStop = false;
            this.toolTip1.SetToolTip(this.pictureBox2, resources.GetString("pictureBox2.ToolTip"));
            this.pictureBox2.Click += new System.EventHandler(this.btnClose_Click);
            // 
            // NotifyForm
            // 
            resources.ApplyResources(this, "$this");
            this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
            this.Controls.Add(this.pictureBox2);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.pictureBox1);
            this.Controls.Add(this.lblText);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.Name = "NotifyForm";
            this.Opacity = 0;
            this.ShowInTaskbar = false;
            this.toolTip1.SetToolTip(this, resources.GetString("$this.ToolTip"));
            this.TopMost = true;
            this.TransparencyKey = System.Drawing.Color.Teal;
            this.MouseEnter += new System.EventHandler(this.NotifyForm_MouseEnter);
            this.MouseLeave += new System.EventHandler(this.NotifyForm_MouseLeave);
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
            this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// Starts notification process by placing NotifyForm to bottom right corner
		/// making it top most window and showing it.
		/// </summary>
		/// <param name="handler">Callback gets notified about user interaction with NotifyForm. Most likely
		/// it is NoteForm.HandleNotifyAction() method.</param>
		internal void StartNotification(NotifyActionHandler handler)
		{
			this.NotificationHandler += handler;
			timerFading.Enabled = true;
			this.SetDesktopLocation(SystemInformation.WorkingArea.Size.Width - this.Size.Width,
				SystemInformation.WorkingArea.Size.Height - this.Size.Height);
			//Makes the window top most on the system.
			WinImports.SetWindowPos( this.Handle, new IntPtr(WinImports.HWND_TOPMOST), 0,0,0,0, 
					WinImports.SWP_NOMOVE | WinImports.SWP_NOSIZE | WinImports.SWP_NOOWNERZORDER);
			this.Show();
			this.BringToFront();
			//this.TopMost = true;
		}


		/// <summary>
		/// Tick handler.  Fade in. Fade out.
		/// </summary>
		/// <param name="sender">unused</param>
		/// <param name="e">unused</param>
		private void FadeTick(object sender, System.EventArgs e)
		{
			switch ( this.state )
			{
				case NotifyState.FadeUp:
					DoFadeIn();
					break;
				case NotifyState.Visible:
					StartFadeOut();
					break;
				case NotifyState.FadeDown:
					DoFadeDown();
					break;
			}
		}

		/// <summary>
		/// Increase the opacity of the toast window. 
		/// </summary>
		/// <remarks>
		/// Once totally faded in, stay visible for 
		/// 3 full seconds.
		/// </remarks>
		private void DoFadeIn()
		{
			if ( this.Opacity < 0.99 )
			{
				this.Opacity += 0.05;
				this.Update();
			}
			else // Stop this timer and start a new one:
			{
				this.state = NotifyState.Visible;
				this.timerFading.Interval = 3000;
			}
		}

		/// <summary>
		/// Fade out.
		/// </summary>
		/// <remarks>
		/// Lower the opacity until the window is gone.
		/// Then close.
		/// </remarks>
		private void DoFadeDown()
		{
			if ( this.Opacity > 0.01 )
			{
				this.Opacity -= 0.05;
				this.Update();
			}
			else
			{
				if (null != NotificationHandler)
				{
					NotificationHandler(this, new NotifyActionEventArgs(NotifyForm.Action.Missed));
				}
				this.Close();
			}
		}

		/// <summary>
		/// Transition from up to fade out.
		/// </summary>
		private void StartFadeOut()
		{
			this.timerFading.Interval = 100;
			this.state = NotifyState.FadeDown;
		}

		/// <summary>
		/// Closes NotifyForm and calls back NotificationHandler with status Closed
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void btnClose_Click(object sender, System.EventArgs e)
		{
			timerFading.Enabled = false;
			if (null != NotificationHandler)
			{
				NotificationHandler(this, new NotifyActionEventArgs(NotifyForm.Action.Closed));
			}
			this.Close();
		}

		/// <summary>
		/// Text of notify form was clicked by user.
		/// Closes NotifyForm and calls back NotificationHandler with status Selected
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void lblText_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)
		{
			timerFading.Enabled = false;
			if (null != NotificationHandler)
			{
				NotificationHandler(this, new NotifyActionEventArgs(NotifyForm.Action.Selected));
			}
			this.Close();
		}

		private void NotifyForm_MouseEnter(object sender, System.EventArgs e)
		{
			this.Opacity = 1.0;
			this.Invalidate(true);
			this.StartFadeOut();
			timerFading.Enabled = false;

		}

		private void NotifyForm_MouseLeave(object sender, System.EventArgs e)
		{
			this.StartFadeOut();
			timerFading.Enabled = true;
		}

	}

	
	/// <summary>
	/// This class describes the arguments used for 
	/// the event arguments when the Notify form finished.
	/// </summary>
	public class NotifyActionEventArgs : System.EventArgs
	{
		/// <summary>
		/// 
		/// </summary>
		private readonly NotifyForm.Action action;

		/// <summary>
		/// Retrieve the toast open arguments.
		/// </summary>
		public NotifyForm.Action NotifyAction
		{
			get
			{
				return action;
			}
		}

		/// <summary>
		/// Single constructor.
		/// </summary>
		/// <param name="ToastArgs">The toast arguments.</param>
		public NotifyActionEventArgs( NotifyForm.Action action )
		{
			this.action = action;
		}
	}

	/// <summary>
	/// Class interested in receiving feedback from NotifyForm has to impletement this event
	/// handler.
	/// </summary>
	public delegate void NotifyActionHandler( object sender, NotifyActionEventArgs args );
}

